package indexing;

import java.io.File;
import java.io.IOException;

import org.apache.lucene.analysis.WhitespaceAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.Fieldable;
import org.apache.lucene.index.CorruptIndexException;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.queryParser.ParseException;
import org.apache.lucene.queryParser.QueryParser;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TopScoreDocCollector;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.util.Version;

public class IndexWord {

	private WhitespaceAnalyzer analyzer_2;
	private FSDirectory dir_2;
	private IndexWriterConfig config_2;
	private IndexWriter w_2;
	private Document doc;
	//Attributes used in the method "verifyWordExist()"
	private int hitsPerPage = 10;
	private IndexReader reader;
	private IndexSearcher searcher;
	private TopScoreDocCollector collector;
	private ScoreDoc[] hits;
	private String qField="word";
	//Attributes used in the method "cleanInformation()"
	private int endPos;
	private String cleanInfo;
	/**
	 * Method called to initialize the attributes of the class
	 * @param String indexDir Main directory where the folder index_w will be stored- 
	 */
	public void init(String indexDir)throws Exception{
		/**
		 * Example of use of PerFieldAnalyzer:
		 * 	http://lucene.472066.n3.nabble.com/PerFieldAnalyzerWrapper-use-Analyzer-s-not-being-used-as-expected-td541413.html
		 * new way
		 * 	http://lucene.apache.org/core/old_versioned_docs/versions/3_5_0/api/core/org/apache/lucene/analysis/PerFieldAnalyzerWrapper.html
		 */
		this.analyzer_2 = new WhitespaceAnalyzer(Version.LUCENE_35);
		if(System.getProperty("os.name").toLowerCase().indexOf("win")>=0)
			this.dir_2 = FSDirectory.open(new File(indexDir+"\\index_w"));
		else
			this.dir_2 = FSDirectory.open(new File(indexDir+"/index_w"));
		this.config_2 = new IndexWriterConfig(Version.LUCENE_35,analyzer_2);
		this.w_2=new IndexWriter(this.dir_2, this.config_2);
	}
	public void closeIndexWriter()throws IOException{
		w_2.close();
	}
	/**
	 * This method index a positive term.
	 * @param String word
	 */
	public void addPositWord(String word) throws CorruptIndexException, IOException{
	    this.doc= new Document();
	    this.doc.add((Fieldable) new Field("word",word, Field.Store.YES, Field.Index.ANALYZED));
	    this.doc.add((Fieldable) new Field("class", "positive", Field.Store.YES, Field.Index.NO));
	    this.w_2.addDocument(this.doc);
	}
	/**
	 * This method verifies if the word already exist in the index.
	 * The method was created to be run before "addNegtWord(String word)" in order
	 * to avoid the existence of a word with two classes.
	 * @param String qword Queried word. 
	 */
	public void verifyWordExist(String qword) throws ParseException,CorruptIndexException, IOException{
		Query q = new QueryParser(Version.LUCENE_35,qField, analyzer_2).parse(qword);
		//Building the scoring
		this.reader = IndexReader.open(dir_2);
		this.searcher = new IndexSearcher(this.reader);
		this.collector = TopScoreDocCollector.create(this.hitsPerPage, true);
		searcher.search(q, collector);
		this.hits = collector.topDocs().scoreDocs;
		//Showing
		if(this.hits.length>0)
			System.err.println("Found " + hits.length + " hits."+"---Searched word: "+qword);
	}
	/**
	 * This method close the searcher in order to start index tasks again.
	 */
	public void closeSearcher() throws IOException{
		this.searcher.close();
		this.reader.close();
	}
	/**
	 * This method index a negative term.
	 * @param String word
	 */
	public void addNegtWord(String word) throws CorruptIndexException, IOException{
	    this.doc= new Document();
	    this.doc.add((Fieldable) new Field("word",word, Field.Store.YES, Field.Index.ANALYZED));
	    this.doc.add((Fieldable) new Field("class", "negative", Field.Store.YES, Field.Index.NO));
	    this.w_2.addDocument(this.doc);
	}
	/**
	 * This method delete the archive headers, which are useless and return only the useful information.
	 * @param String infoBlock Is the block information that is going to be analyze
	 */
	public String cleanInformation(String infoblock){
		this.cleanInfo="";
		this.endPos=infoblock.lastIndexOf(";");
		this.cleanInfo=infoblock.substring(this.endPos, infoblock.length());
		return this.cleanInfo;
	}
}
